using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace tutFuelCellGame
{
    public class GameObject
    {
        public Model Model { get; set; }
        public float Orientation { get; set; }
        public Vector3 Position { get; set; }
        public float Alpha { get; set; }
        public float ShadowAlpha { get; set; }
        public bool IsActive { get; set; }
        public BoundingSphere BoundingSphere { get; set; }
        public float Scale { get; set; }
        public LightSource lightSource1 { get; set; }
        public LightSource lightSource2 { get; set; }

        public GameObject()
        {
            Model = null;
            Position = Vector3.Zero;
            Orientation = 0f;
            IsActive = false;
            BoundingSphere = new BoundingSphere();
            Scale = 1f;
            lightSource1 = null;
            lightSource2 = null;
            Alpha = 1f;
            ShadowAlpha = 0.5f;
        }

        protected BoundingSphere CalculateBoundingSphere(float scalingFactor)
        {
            BoundingSphere mergedSphere;
            BoundingSphere[] boundingSpheres;
            int index = 0;
            int meshCount = Model.Meshes.Count;

            boundingSpheres = new BoundingSphere[meshCount];
            foreach (ModelMesh mesh in Model.Meshes)
            {
                boundingSpheres[index++] = mesh.BoundingSphere;
            }

            mergedSphere = boundingSpheres[0];
            if ((Model.Meshes.Count) > 1)
            {
                index = 1;
                do
                {
                    mergedSphere = BoundingSphere.CreateMerged(mergedSphere, boundingSpheres[index]);
                    index++;
                } while (index < Model.Meshes.Count);
            }
            mergedSphere.Center.Y = 0;
            mergedSphere.Radius *= Scale * scalingFactor;
            return mergedSphere;
        }

        public virtual void DrawBoundingSphere(Matrix view, Matrix projection, Model boundingSphereModel)
        {
            //DrawInnerBoundingSpheres(boundingSphereModel, view, projection);
            DrawBoundingSphere(view, projection, boundingSphereModel, BoundingSphere);
        }

        public virtual void DrawBoundingSphere(Matrix view, Matrix projection, Model boundingSphereModel, BoundingSphere boundingSphere)
        {
            DrawBoundingSphere(view, projection, boundingSphereModel, boundingSphere, Color.WhiteSmoke);
        }

        protected void DrawBoundingSphere(Matrix view, Matrix projection, Model boundingSphereModel, BoundingSphere boundingSphere, Color color)
        {
            //DrawInnerBoundingSpheres(boundingSphereModel, view, projection);

            Matrix scaleMatrix = Matrix.CreateScale(boundingSphere.Radius);
            Matrix translateMatrix = Matrix.CreateTranslation(boundingSphere.Center);
            Matrix worldMatrix = scaleMatrix * translateMatrix;

            foreach (ModelMesh mesh in boundingSphereModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = worldMatrix;
                    effect.View = view;
                    effect.AmbientLightColor = color.ToVector3();
                    effect.Projection = projection;
                }
                mesh.Draw();
            }
        }

        protected void DrawModelMeshes(Matrix worldMatrix, Matrix view, Matrix projection)
        {
            Matrix[] transforms = new Matrix[Model.Bones.Count];
            Model.CopyAbsoluteBoneTransformsTo(transforms);
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = worldMatrix * transforms[mesh.ParentBone.Index];
                    effect.View = view;
                    effect.Projection = projection;
                    effect.Alpha = Alpha;
                    effect.EnableDefaultLighting();
                    if (lightSource1 != null)
                        lightSource1.ApplyLight(effect.DirectionalLight0);
                    if (lightSource2 != null)
                        lightSource2.ApplyLight(effect.DirectionalLight1);
                    else 
                        effect.DirectionalLight1.Enabled = false;
                    effect.DirectionalLight2.Enabled = false;
                    effect.PreferPerPixelLighting = true;
                }
                mesh.Draw();
            }
        }

        protected void DrawModelMeshesWithShadow(Matrix worldMatrix, Matrix view, Matrix projection, Matrix shadow)
        {
            Matrix[] transforms = new Matrix[Model.Bones.Count];
            Model.CopyAbsoluteBoneTransformsTo(transforms);
            Matrix worldShadow = worldMatrix * shadow;
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.AmbientLightColor = Vector3.Zero;
                    effect.Alpha = ShadowAlpha;
                    effect.DirectionalLight0.Enabled = false;
                    effect.DirectionalLight1.Enabled = false;
                    effect.DirectionalLight2.Enabled = false;
                    effect.View = view;
                    effect.Projection = projection;
                    effect.World = worldShadow * transforms[mesh.ParentBone.Index];
                }
                mesh.Draw();
            }
        }

    }
}